package com.redwinter.logkit.sdk.context;

import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Stack;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author goudadong
 * @description 日志SpEL表达式变量上下文
 * @datetime 2021-12-15 14:24
 * @email 2360564660@qq.com
 **/
public class LogSpELVarContext {

    private static final ThreadLocal<Stack<Map<String, Object>>> variableMapStack = new ThreadLocal<>();
    private static final Map<String, String> variableMapRef = new ConcurrentHashMap<>(16);
    private static final String PRE_KEY = "custom_";
    private static final AtomicInteger seq = new AtomicInteger(0);

    /**
     * 设置值
     *
     * @param name  变量名
     * @param value 变量值
     */
    public static void putVariables(String name, Object value) {
        String key = PRE_KEY + seq.incrementAndGet();
        variableMapRef.put(name, key);
        if (Objects.isNull(variableMapStack.get())) {
            Stack<Map<String, Object>> data = new Stack<>();
            variableMapStack.set(data);
        }
        Stack<Map<String, Object>> data = variableMapStack.get();
        if (data.isEmpty()) {
            data.push(new HashMap<>());
        }
        data.peek().put(key + name, value);
    }

    /**
     * 获取变量数据
     *
     * @return key-value
     */
    public static Map<String, Object> getVariables() {
        Stack<Map<String, Object>> data = variableMapStack.get();
        return Objects.nonNull(data) ? data.peek() : new HashMap<>();
    }

    /**
     * 获取真正的名称
     *
     * @param name 用户输入的自定义的名称
     * @return 真正需要解析的名称
     */
    public static String getRelName(String name) {
        String key = variableMapRef.get(name);
        return StringUtils.isEmpty(key) ? null : key + name;
    }

    /**
     * 清理数据
     */
    public static void clear() {
        Stack<Map<String, Object>> data = variableMapStack.get();
        if (Objects.nonNull(data)) {
            data.pop();
        }
        variableMapStack.remove();
        variableMapRef.clear();
    }
}
